package com.example.demo.config;

import com.example.demo.config.shiro.MySessionManager;
import com.example.demo.config.shiro.WebShiroRealm;
import com.example.demo.config.shiro.filter.CookieFilter;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfiguration {

    @Bean
    public Cookie getCookie() {
        SimpleCookie cookie = new SimpleCookie();

        cookie.setPath("/");
        cookie.setMaxAge(SimpleCookie.DEFAULT_MAX_AGE);
        cookie.setVersion(SimpleCookie.DEFAULT_VERSION);
        cookie.setSecure(Boolean.FALSE);
        cookie.setHttpOnly(Boolean.TRUE);

        return cookie;
    }

//    @Bean
//    public EhCacheManager getEhCacheManager(){
//        EhCacheManager ehcacheManager = new EhCacheManager();
//        ehcacheManager.setCacheManagerConfigFile("classpath:config/ehcache-shiro.xml");
//        return ehcacheManager;
//    }

    @Bean(name = "credentialsMatcher")
    public SimpleCredentialsMatcher createSimpleCredentialsMatcher(CacheManager cacheManager) {
//        return new CustomCredentialsMatcher(cacheManager);
        return new SimpleCredentialsMatcher();
    }

    @Bean
    public SessionManager sessionManager(CacheManager cacheManager){
//        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//        sessionManager.setGlobalSessionTimeout(1800000);
//        sessionManager.setDeleteInvalidSessions(true);
//        sessionManager.setSessionValidationSchedulerEnabled(false); //关闭session检查，否则会乱扫描redis
//        //sessionManager.setSessionValidationScheduler(scheduler);
//        sessionManager.setSessionIdCookieEnabled(true);
//        return sessionManager;

        DefaultWebSessionManager sessionManager = new MySessionManager();
        // sessionDAO
//        new MySessionManager().setSessionDAO();
        EnterpriseCacheSessionDAO sessionDAO = new EnterpriseCacheSessionDAO();
        sessionDAO.setCacheManager(cacheManager);
        sessionManager.setSessionDAO(sessionDAO);


        return sessionManager;
    }


    @Bean(name = "webShiroRealm")
    public WebShiroRealm myShiroRealm(CacheManager cacheManager){
        WebShiroRealm realm = new WebShiroRealm();
        realm.setCacheManager(cacheManager);
        // 设置密码比对方式
//        realm.setCredentialsMatcher(matcher);
        return realm;
    }

    @Bean(name = "securityManager")
    @Autowired
    public DefaultWebSecurityManager defaultWebSecurityManager(WebShiroRealm realm, SessionManager sessionManager, CacheManager cacheManager){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //设置realm， 可设置多个，按照相应的顺序及策略进行访问
        realm.setCacheManager(cacheManager);
        securityManager.setRealms(Arrays.asList(realm));
        securityManager.setCacheManager(cacheManager);
        securityManager.setSessionManager(sessionManager);

        SecurityUtils.setSecurityManager(securityManager);

//        CookieRememberMeManager
//        securityManager.setRememberMeManager();

//        //设置authenticator,
//        ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
//        // realm过滤
//        authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
//        authenticator.setRealms(Arrays.asList(realm));
//        securityManager.setAuthenticator(authenticator);
        return securityManager;
    }


    @Bean(name = "shiroFilter")
    @Autowired
    public AbstractShiroFilter shiroFilterFactoryBean(DefaultWebSecurityManager securityManager,
//                                         MyAuthorizationFilter authorizationFilter,
//                                         LoginConfigProperties loginConfig,
                                                      CookieFilter cookieFilter,
                                              ServerProperties serverProperties
    ) throws Exception{
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();

        factoryBean.setSecurityManager(securityManager);
        factoryBean.setLoginUrl("/page/login"); // 如果不设置默认会自动寻找Web工程根目录下的"/login.html"页面
        factoryBean.setSuccessUrl("/success"); // 登录成功后要跳转的连接
        factoryBean.setUnauthorizedUrl("/403");

//        shiroFilter.setSecurityManager(securityManager);
        Map<String, Filter> filters = new HashMap<>();
        filters.put("cookieFilter", cookieFilter);
//        filters.put("authc", new FormAuthenticationFilter());
//        filters.put("perm", authorizationFilter);
        factoryBean.setFilters(filters);
        /*
         * 加载ShiroFilter权限控制规则
         * 下面这些规则配置最好配置到配置文件中
         * */
        Map<String, String> filterChainMap = new LinkedHashMap<String, String>();
        /*
         * authc：该过滤器下的页面必须验证后才能访问，它是Shiro内置的一个拦截器
         * org.apache.shiro.web.filter.authc.FormAuthenticationFilter
         *      anon：它对应的过滤器里面是空的,什么都没做,可以理解为不拦截
         *      authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
         */
//        filterChainMap.put("/register", "anon");
//        filterChainMap.put("/register/**", "anon");
//        filterChainMap.put("/permission/userInsert", "anon");
//        filterChainMap.put("/error", "anon");
//        filterChainMap.put("/tUser/insert","anon");
        setAnon(filterChainMap);
        filterChainMap.put("/**", "cookieFilter");
        filterChainMap.put("/**", "authc");

//        filterChainMap.put("/**", "authc");

        factoryBean.setFilterChainDefinitionMap(filterChainMap);
//        logger.info("shiro拦截器工厂类注入成功");


        return (AbstractShiroFilter)factoryBean.getObject();
    }

    /*设置匿名登录*/
    private void setAnon(Map<String, String> filterChainMap) {
        filterChainMap.put("/**.ico", "anon");
        filterChainMap.put("/**/jpg", "anon");
        filterChainMap.put("/page/**", "anon");
        filterChainMap.put("/register", "anon");
        filterChainMap.put("/login", "anon");
    }

}
